# Create your views here.
import base64

from django.contrib.auth import get_user_model
from django_redis import get_redis_connection

from rest_framework.response import Response
from rest_framework.views import APIView
from captcha.views import CaptchaStore, captcha_image

from meiduo_mall_new.utils.yunpian import YunPian
from . import constants
from .serializers import CheckImageCodeSerializer, CheckSMSCodeByTokenSerializer
from rest_framework import viewsets, mixins, status

from celery_task.sms.tasks import send_sms_code

import random

User = get_user_model()


class ImageCode(APIView):
    """
    图片验证码
    """

    def get(self, request):
        hashKey = CaptchaStore.generate_key()

        try:
            imageId = CaptchaStore.objects.get(hashkey=hashKey).id
            image = captcha_image(request, hashKey)
            imageBase64 = base64.b64encode(image.content)
            return Response({
                "success": True,
                "image": imageBase64,
                "image_code_id": imageId
            })
        except:
            return Response({
                "success": False,
                "image": "",
                "image_code_id": ""
            }, status=500)


class SMSCodeView(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = CheckImageCodeSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 检验通过
        mobile = serializer.validated_data["mobile"]
        # 生成短信验证码
        sms_code = '%06d' % random.randint(0, 999999)

        # 保存验证码以及发送记录
        # yun_pian = YunPian(settings.YUNPIAN_APIKEY)
        # sms_status = yun_pian.send_semd(sms_code, mobile=mobile)

        send_sms_code.delay(mobile, sms_code)

        redis_conn = get_redis_connection("verify_codes")

        # 使用redis管道一次执行多个命令
        pipeline = redis_conn.pipeline()
        pipeline.setex(constants.REGISTER_SMS_CODE + ":" + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pipeline.setex(constants.REGISTER_SMS_CODE_FLAG + ":" + mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        pipeline.execute()

        return Response({
            "mobile": mobile
        }, status=status.HTTP_201_CREATED)


class SMSCodeByTokenView(APIView):
    """
    根据access_token
    """

    def post(self, request):
        # 获取并检验access_token
        access_token = request.data["access_token"]
        if access_token is None:
            return Response({
                "message": "缺少access token"
            }, status=status.HTTP_404_NOT_FOUND)

        # 取出手机号
        mobile = User.check_send_sms_code_token(access_token)
        if mobile is None:
            return Response({
                "message": "无效access token"
            }, status=status.HTTP_404_NOT_FOUND)

        # 判断发送次数
        redis_conn = get_redis_connection('verify_codes')
        senf_flag = redis_conn.get(constants.FORGET_SMS_CODE_FLAG + ":" + mobile)
        if senf_flag:
            return Response({
                "message": "发送短信次数过于频繁"
            }, status=status.HTTP_429_TOO_MANY_REQUESTS)

        # 生成短信验证码
        sms_code = '%06d' % random.randint(0, 999999)

        # 保存验证码以及发送记录
        # yun_pian = YunPian(settings.YUNPIAN_APIKEY)
        # sms_status = yun_pian.send_semd(sms_code, mobile=mobile)

        send_sms_code.delay(mobile, sms_code)

        redis_conn = get_redis_connection("verify_codes")

        # 使用redis管道一次执行多个命令
        pipeline = redis_conn.pipeline()
        pipeline.setex(constants.FORGET_SMS_CODE + ":" + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pipeline.setex(constants.FORGET_SMS_CODE_FLAG + ":" + mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        pipeline.execute()

        return Response({
            "mobile": mobile
        }, status=status.HTTP_201_CREATED)


class CheckSMSCodeByToken(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = CheckSMSCodeByTokenSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return Response({
            "message": "校验成功"
        })


class TestCeleryView(APIView):
    def get(self, request):
        # 使用celery发布异步任务
        result = send_sms_code.delay(13695247115, 1234567)

        return Response({
            "mobile": result.task_id
        }, status=status.HTTP_201_CREATED)
